import { Inject, Injectable } from '@nestjs/common';
import { arrayToTree } from 'src/utils/utils';
import { Category } from './category.model';
import { CreateCategoryDto } from './dto/create-category.dto';
import * as Excel from 'exceljs';
import { CategoryQueryDto } from './dto/category-query.dto';
import { Op } from 'sequelize';
import { Logger } from 'src/utils/log4js';

@Injectable()
export class CategoryService {
  constructor(
    @Inject('CategoryRepository')
    private readonly categoryRepository: typeof Category,
  ) {}

  static getProjectCell(target, key, value) {
    const handler = {
      1: (target, value) => {
        target.pid = value;
      },
      2: (target, value) => {
        target.name = value;
      },
      3: (target, value) => {
        target.icon = value;
      },
      4: (target, value) => {
        target.flag = value;
      },
      5: (target, value) => {
        target.sort = value;
      },
    };
    handler[key] && handler[key](target, value);
  }

  async findAll(query: CategoryQueryDto): Promise<any> {
    // eslint-disable-next-line prefer-const
    let { orderBy, sort, ...params } = query;
    orderBy = query.orderBy || 'sort';
    sort = query.sort || 'DESC';

    const queryParams = [] as any;
    Object.keys(params).forEach((key) => {
      if (params[key]) {
        queryParams.push({
          [key]: { [Op.like]: `%${params[key].trim()}%` },
        }); // 模糊查询
      }
    });

    const { rows, count } = await this.categoryRepository.findAndCountAll({
      order: [[orderBy, sort]],
      where: queryParams.length > 0 ? { [Op.or]: queryParams } : {},
      raw: true,
    });
    if (rows) {
      const treeList = arrayToTree(rows); // 转换成树状结构
      return {
        data: { list: treeList, total: count },
      };
    }
  }

  async add(payload: CreateCategoryDto): Promise<any> {
    const { name } = payload;
    const category = await this.categoryRepository.findOne({
      where: { name },
    });
    if (category) {
      return {
        code: -1,
        msg: '类别已存在',
      };
    }
    const data = {
      ...payload,
      create_time: new Date(),
      update_time: new Date(),
    };
    const result = await this.categoryRepository.create(data);
    await result.save();
    return { msg: '类别添加成功' };
  }

  async update(payload: CreateCategoryDto, id: number): Promise<any> {
    const { name } = payload;
    const category = await this.categoryRepository.findOne({
      where: { name },
    });
    if (category && category.id !== id) {
      return {
        code: -1,
        msg: '类别已存在',
      };
    }
    const data = {
      ...payload,
      update_time: new Date(),
    };
    await this.categoryRepository.update(data, {
      where: { id },
    });
    return { msg: '类别修改成功' };
  }

  async delete(id: number): Promise<any> {
    const category = await this.categoryRepository.findOne({
      where: { pid: id },
    });
    if (category) {
      return {
        code: -1,
        msg: '该类别下有子类别，不能删除',
      };
    }
    await this.categoryRepository.destroy({ where: { id } });
    return { msg: '类别删除成功' };
  }

  // TODO: 导入excel
  async import(file: any): Promise<any> {
    try {
      const { buffer } = file;
      const workbook = new Excel.Workbook();
      await workbook.xlsx.load(buffer); // 加载buffer文件
      const worksheet = workbook.getWorksheet(1); // 获取excel表格的第一个sheet
      const result = [];
      worksheet.eachRow((row, rowNumber) => {
        // 第一行是表头，故从第二行获取数据
        if (rowNumber > 1) {
          const target = {};
          row.eachCell((cell, colNumber) => {
            CategoryService.getProjectCell(target, colNumber, cell.value);
          });
          result.push(target);
        }
      });
      return {
        data: result,
      };
    } catch (err) {
      Logger.error(err);
      return {
        data: null,
        code: -1,
        msg: '导入失败',
      };
    }
  }
}
